FuckingReach: схема новой rod-centric системы
=============================================

Статус документа
----------------

Это рабочий план для дальнейшей переделки многофайловой версии скрипта.
Текущая структура уже вынесена в `FuckingReach.cslist` и набор `partial class
FuckingReach` файлов. Этот документ описывает, как дальше безопасно переходить
от старой смешанной логики к новой системе на основе synthetic shaft и synthetic
orifice.

Глобальное правило для live-систем движения/наведения:

- не использовать кэш для текущих позиций, ротаций, костей, контроллеров и
  вычисляемых состояний, если эти данные влияют на точность движения в кадре;
  брать актуальные значения напрямую каждый апдейт. Кэш в таких местах портит
  точность, дает запаздывание/рассинхрон и ломает подстройку.

Текущее дополнение по Paudi motion:

- добавлен новый ручной режим `Качание бедрами 2`;
- режим не должен уводить `hipControl` через `paudiMotionWorldOffset`, потому что
  эта точка держит высоту/глубину траста;
- визуальная и позовая работа режима должна идти через secondary rig:
  `pelvisControl`, `abdomenControl`, `abdomen2Control`, `lThighControl`,
  `rThighControl`;
- сами бедра получают мягкий pitch через `femaleHipRB.AddTorque(...)`, чтобы
  риг качался физикой, а не телепортом контроллера;
- для режима заведены только 4 ручки:
  `сила`, `вынос thigh (cm)`, `низ thigh (cm)`, `запаздывание`.

Последние прикладные правки (2026-04-24):

- `Жесткое управление` теперь стартует выключенным по умолчанию; в выключенном
  состоянии сохраняется текущий auto-freeze-after-stable режим, а во
  включенном состоянии риг остается активным во время траста; синхронизация
  после полной сборки UI/после `RestoreFromJSON` оставлена, чтобы режим работал
  сразу без первого ручного переключения;
- arousal-апдейт (`UpdateArousalSystem` и trigger runtime) поднят выше в
  `Update`, сразу после обновления сглаженных penis/orifice данных, чтобы
  `Arousal level` не зависел от более поздних ранних `return` по alignment /
  pose-pause / target-state; временная callback-синхронизация arousal убрана,
  чтобы поведение снова было ближе к рабочему монолиту
  `FuckingReach_V5_rigibody`;
- в блоке arousal на главной странице добавлена кнопка `Настройки возбуждения`;
  она открывает отдельную submenu-страницу с собственным `Back`, сделанную по
  той же схеме, что и `Penis settings`, чтобы дальше можно было переносить туда
  отдельные элементы UI;
- внутри `Настройки возбуждения` добавлены вложенные страницы `Эмоции`,
  `Дыхание`, `Поцелуи`: `Поцелуи` пока содержит только `Back`, а эмоции и
  дыхание получили собственные storables/UI и runtime в
  `FuckingReach.ArousalPresentationUI.cs` +
  `FuckingReach.ArousalPresentation.cs`;
- arousal presentation теперь разделен на независимые слои: натуральная мимика
  и `Ахегао` выбираются режимом и не должны одновременно писать конфликтующие
  face-морфы; `Авто` плавно гасит натуральный слой и усиливает ахегао после
  заданного порога/во время climax;
- дыхание сделано встроенным в этот плагин, без зависимости от VAMMoan:
  частота берется от шкалы возбуждения и скорости траста, глубина - от
  возбуждения/climax, визуально используются morph-цели груди/живота/носа/рта;
- VAMMoan/VAMMoan2Teaser подключается только как внешний voice-контур:
  скрипт ищет plugin storable на female atom, задает `Set Arousal`, `Moaning`
  или `Orgasm`, но не использует его breathing states, чтобы не спорить со
  встроенным дыханием;
- `Enable arousal system` больше не останавливает thrust/prop/knee при
  включении: callback только сбрасывает устаревшее состояние возбуждения и
  orgasm, иначе активный траст терял стимуляцию и шкала падала обратно;
- в `UpdateArousalSystem` добавлен устойчивый arousal-drive от активного
  thrust/prop внутри synthetic channel: если rig/hip держат тело слишком
  стабильно и speed-сенсоры дают почти 0, шкала возбуждения все равно растет,
  пока реально идет траст внутри отверстия;
- при ручном переключении `Vagina <-> Anus` дополнительно сбрасывается
  `smart thrust hip anchor`, чтобы старый mounted-state не держал прошлое
  отверстие;
- если auto-freeze отпускает систему по force release или после 2 секунд без
  валидного mounted-state, одновременно сбрасывается mounted-anchor и Smart
  снова может сделать полный re-approach;
- удержание уже активного auto-freeze теперь проверяется по строгому mounted
  состоянию выбранного synthetic отверстия;
- `Hip sliders rotate hips` по умолчанию выключен;
- `Left/right limit (°)` по умолчанию = `0`, `Up/down limit (°)` по
  умолчанию = `70`;
- `Simple switch retreat to head/neck (cm)` по умолчанию = `12.0`.
- auto-freeze-after-stable теперь идет в два этапа: после подтвержденного
  стабильного траста secondary rig сначала паркуется, но `hip` еще около
  `2.0` секунд продолжает Smart-дожим глубины в solo-режиме; только после
  непрерывного стабильного окна система фиксирует настоящий freeze, а если
  глубина/траст не восстанавливаются в течение `2.0` секунд, полный риг
  включается обратно и делает обычный re-approach заново.
- во время mounted thrust боковая центровка теперь ориентируется не на
  `penisBaseControl`, а на midpoint между левым и правым мужским бедром;
  для этого режима сделан более узкий lateral-коридор, чтобы женский таз и
  отверстие меньше уводило вбок вдоль направления стержня, при этом ось
  глубины и продольное положение по телу мужчины не трогаются.
- arousal presentation теперь полностью завязан на `Arousal level`: натуральная
  мимика, ахегао-глаза и язык не являются статичной маской, а плавно растут от
  шкалы возбуждения; если `Enable arousal system` выключен или шкала на нуле,
  лицо остается только на минимальном слое.
- натуральные эмоции переделаны ближе к логике HK: вместо одновременной записи
  всех face-морфов используются отдельные группы бровей, глаз и рта, где в
  активном диапазоне выбирается один подходящий морф и мягко меняется каждые
  несколько секунд.
- ахегао-язык использует абсолютные целевые значения BodyLanguage
  (`Tongue In-Out`, `Tongue Raise-Lower`, `Tongue Up-Down`, `Tongue Bend Tip`,
  `Tongue Roll 1`) через множитель шкалы возбуждения, а не фиксированное
  состояние; для нормального возврата заданы специальные дефолты языка.
- смена режимов эмоций и кнопка `Reset emotions` больше не делают резкий сброс:
  текущие face-морфы берутся как стартовая точка и в течение примерно секунды
  сглаживаются к нейтрали или новому режиму.
- prop thrust теперь участвует в росте `Arousal level` через собственные
  `propThrustFrequency` и `propThrustForce`, но только когда включен
  `Enable arousal system`.

Важно: первый этап разбиения был механическим. Поведение, формулы, силы и VaM
API не должны считаться уже исправленными только из-за разнесения файлов.


0. Главная цель
---------------

Новая система должна жить по одному правилу:

    Не hip ищет примерную точку, а solver ставит pelvis/hip так, чтобы entry
    point выбранного synthetic отверстия оказался в правильном месте
    относительно synthetic shaft.

Источник истины для подвода, посадки, удержания и траста:

- synthetic shaft;
- synthetic orifice.

Старые данные допустимы только как fallback/debug:

- старые base/mid/tip точки;
- male hip forward;
- corridor/clamp эвристики;
- старый stableDir.

Они не должны быть главным рулем новой системы.


1. Жесткие инварианты
---------------------

1.1. Shaft - единственный источник геометрии стержня

Все Smart/mount/inside/thrust расчеты должны брать геометрию из единой модели:

- shaftStart;
- shaftEnd;
- shaftAxis;
- shaftLength;
- shaftRadius или radius profile;
- projection по параметру `s`;
- closest point on axis;
- closest point on surface.

Нельзя смешивать управляющее направление с maleHip.forward, старым stableDir или
старыми base/mid/tip точками, кроме явно помеченного fallback режима.


1.2. Entry center отверстия

В фазах capture, mount, inside follow и thrust центр входа выбранного отверстия
должен попадать:

- на ось shaft;
- или на явно заданную radial shell, если такой режим специально включен.

Базовое правило:

    entry center сидит на shaft centerline.

Он не должен удерживаться ниже стержня, сбоку от него или в старом corridor.


1.3. Channel axis отверстия

Ось канала отверстия может быть под углом к оси shaft. Это нормально и нужно для
естественных поз.

Ограничения:

- угол держится внутри comfort cone;
- inward/outward знак не прыгает;
- ось не флипается от кадра к кадру;
- слайдеры дают bias позы, но не ломают посадку entry на shaft.


1.4. Solver решает позу, а не простой delta

Старая логика, которую надо убирать из управляющего ядра:

    desiredHip = hip + (aimPoint - orificePos)

Новая логика:

    найти такой target для pelvis/hip, при котором:
    entryPointWorld -> targetEntryWorld
    channelAxisWorld -> desired/allowed channel direction

Delta можно использовать только как внутренний результат solver-а, а не как
основную математику маршрута.


1.5. Запрет Y/Z вращения бедер во время подвода и одевания

Во время фаз:

- `Rendezvous`;
- `TipCapture`;
- `AxisMount`;
- первичное позиционирование выбранного отверстия перед shaft;
- одевание выбранного отверстия на shaft;

запрещено вводить управляющее вращение по Y и Z для:

- `hipControl`;
- pelvis/hip target, если он используется как часть общего бедренного рига;
- связанных контроллеров бедренного рига, если они следуют за hip;
- secondary rig targets, если они создают yaw/roll вместо нормального подвода.

Разрешенное поведение в этих фазах:

- позиционное движение pelvis/hip/рига;
- ограниченный X/pitch correction, если он нужен для естественного угла канала;
- мягкое сохранение исходной позы без скручивания;
- только аварийная коррекция, если без нее будет физический взрыв.

Запрещенное поведение:

- кренить бедра по Z;
- выворачивать бедра по Y;
- компенсировать плохой approach поворотом hip вместо правильного targetEntry;
- давать Paudi/body sliders/legacy guards добавлять Y/Z rotation во время outside
  capture и mount.

Практическое правило для solver-а:

    На outside/mount фазах Y/Z rotation берется из исходной baseline-позы или
    явно сохраняется, а solver решает посадку через позицию entry и допустимый
    X/pitch, не через yaw/roll бедер.


1.6. Боковое центрирование относительно мужчины

Во время mount/inside/thrust можно мягко подтягивать бедра к середине мужского
таза, но центр считать от базы synthetic shaft, то есть от точки, откуда
растет стержень.

Рабочая боковая ось: локальная left/right ось male hip/pelvis,
спроецированная в плоскость, перпендикулярную shaft axis. Это нужно, чтобы
мужские бедра могли уходить в стороны, но женский hip/entry мягко возвращался
к центру стержня, а не оставался замороженным в старой мировой точке.

Запрещено использовать это как общий clamp позы:

- не ограничивать движение вдоль тела мужчины к ногам или голове;
- не ограничивать естественную глубину/высоту подвода;
- не возвращать старый full male-anchor clamp как скрытый route controller.

Задача этого слоя - убрать левый/правый срыв бедер при трасте, не ломая
естественный выбор положения по остальным осям.

Текущая свободная зона бокового центрирования: 5 см суммарно (±2.5 см).


1.7. Мягкий positional anchor бедер во время mounted thrust

Когда selected synthetic entry уже на стержне, hold depth достигнут и thrust
разрешен, можно захватить текущую позицию hip Rigidbody как мягкий якорь.

Правила:

- anchor включается только после успешного `IsSmartRodThrustMounted`;
- anchor захватывает позицию один раз в момент начала mounted thrust и не
  переустанавливается, пока mount остается валидным;
- свободная зона вокруг anchor: 5 см;
- за пределами зоны применяется мягкая позиционная пружина к hip Rigidbody;
- HipApproach во время активного anchor не должен синхронизировать axial target с
  текущим drift Rigidbody, иначе бедра начнут ползти за стержнем;
- torque не применяется, поэтому X/pitch rotation остается свободной для
  подстройки;
- при кратком провале depth/lateral/axis во время mounted thrust включается
  короткая hysteresis-зона: не запускать reinsert/retreat по одному плохому
  кадру;
- если стержень действительно вылетел из отверстия и hysteresis больше не
  держит mount, anchor сбрасывается, чтобы approach/mount могли снова двигать
  бедра.


2. Что должно уйти из главного управляющего контура
--------------------------------------------------

Не обязательно физически удалить в первый проход. Но эти системы не должны
диктовать маршрут в новых фазах.

2.1. Старые источники направления

Вывести из управляющей Smart-навигации:

- `GetStablePenisDirection()` как главный источник направления, если там есть
  смешивание с maleHip.forward или старыми точками;
- все, что берет управляющий shaftAxis из base/mid/tip вместо synthetic shaft;
- любую стабилизацию направления, которая спорит с shaft truth.


2.2. Старые outside assists

На фазах `Rendezvous`, `TipCapture`, `AxisMount` временно отключать или обходить:

- `ClampHipToMaleAnchor`;
- `ClampHipToPenisSafety`;
- `ClampHipToTipChestCorridor`;
- старые entry rail offsets;
- old axis backoff;
- старый smart reinsert;
- старый outside `GetSmartAimPoint`, если он не является тонкой оберткой над
  новым planner;
- Paudi direct offset, если он перехватывает outside-capture.

Оставить только аварийные safety-ограничения:

- anti-teleport;
- anti-explosion;
- простой reject опасного body penetration.


2.3. Динамические sign-flip механики

Убрать из нового ядра:

- re-sign канала от стороны подхода;
- переопределение inward/outward по текущему положению shaft;
- vertex-driven флипы входа/выхода каждый кадр.

Entry point и channel axis должны быть стабильны в pelvis-local или в другом
стабильном локальном пространстве.


3. Архитектура
--------------

Сейчас код разнесен по partial-файлам. Следующий шаг - не сразу внешние
контроллеры, а новые логические блоки внутри `partial class FuckingReach`.
Когда поведение стабилизируется, отдельные блоки можно будет превратить в
настоящие классы.


3.1. Geometry Layer

Задача: только геометрия, без поведения и clamp-ов.

Планируемые сущности:

- `ShaftTruth`;
- `OrificeTruth`;
- `SyntheticShaftModel`;
- `SyntheticOrificeModel`;
- `GeometryProjectionUtil`.

Минимальные данные shaft:

- `Start`;
- `End`;
- `Axis`;
- `Length`;
- `Radius`;
- `GetPoint(s)`;
- `ProjectS(worldPoint)`;
- `ClosestPointOnAxis(worldPoint)`;
- `ClosestPointOnSurface(worldPoint)`;
- `GetFrameAt(s)`.

Минимальные данные orifice:

- active key;
- entry point local/world;
- channel axis local/world;
- entry radius;
- channel length;
- preferred up;
- comfort cone;
- twist reference.

Рекомендуемые будущие файлы:

- `FuckingReach.Geometry.ShaftTruth.cs`;
- `FuckingReach.Geometry.OrificeTruth.cs`.


3.2. Planner / State Layer

Задача: решить, что система хочет сделать сейчас, но не двигать контроллеры.

Фазы:

- `AcquireTarget`;
- `Rendezvous`;
- `TipCapture`;
- `AxisMount`;
- `InsideFollow`;
- `Thrust`;
- `Recover`.

Смысл фаз:

- `AcquireTarget`: выбрать shaft, active orifice, собрать truth.
- `Rendezvous`: вывести entry в свободную точку около начала shaft, с clearance.
- `TipCapture`: подвести entry к shaftStart/pre-entry и посадить на ось.
- `AxisMount`: двигать entry вдоль оси shaft до holdDepth.
- `InsideFollow`: держать entry на оси и удерживать глубину.
- `Thrust`: менять глубину по параметру `s`, не пересчитывая маршрут заново.
- `Recover`: при срыве вернуться в Rendezvous или TipCapture, а не в старый хаос.

Текущий первый файл:

- `FuckingReach.SmartPlanner.cs`.

На текущем шаге черновой файл уже существует, но временно исключен из
`FuckingReach.cslist` после краша VaM. Следующий возврат planner-а должен быть
меньше: сначала C# 6 enum/phase helpers без overload-ов и без влияния на hot
path, затем отдельная проверка загрузки.


3.3. Pose Solver Layer

Задача: из targetEntry и desiredChannel получить конкретное движение pelvis/hip.

Вход:

- текущий pelvis/hip transform;
- entryPointLocal;
- channelAxisLocal;
- targetEntryWorld;
- desiredChannelWorld;
- настройки слайдеров;
- phase weights;
- safety limits.

Выход:

- pelvis/hip target position;
- pelvis/hip target rotation;
- entry position error;
- lateral error to shaft;
- depth error;
- channel angle error;
- twist error;
- флаги ограничения/клампа.

Дополнительное обязательное ограничение solver-а:

- на фазах `Rendezvous`, `TipCapture` и `AxisMount` не создавать управляющий
  Y/Z rotation для hip/бедренного рига;
- если alignment требует сильного Y/Z, planner должен перестроить target или
  route, а не скручивать бедра;
- любые слайдеры Y/Z в этих фазах должны либо игнорироваться, либо применяться
  только как сохраненный baseline без активного доворачивания.

Рекомендуемый будущий файл:

- `FuckingReach.SmartSolver.cs`.


3.4. Constraint / Guards Layer

Задача: страховка, а не навигация.

Оставить как вторичный слой:

- anti-explosion clamp;
- anti-teleport clamp;
- body collision backstop;
- deep penetration safety;
- depth limit;
- velocity/force caps.

Нельзя, чтобы guards выбирали главный route к shaft.

Рекомендуемый будущий файл:

- `FuckingReach.Guards.cs`.


3.5. Thrust Layer

Задача: после mount двигать систему вдоль shaft.

Правила:

- thrust работает по параметру `s`;
- entry center остается на shaft axis;
- channel angle удерживается solver-ом;
- rigidbody force thrust можно оставить, но он работает после capture/mount;
- thrust не должен заново гадать outside aim.

Текущий основной файл:

- `FuckingReach.ThrustAndArousal.cs`.


3.6. Paudi Layer

Paudi должна стать high-level decision layer.

Paudi может решать:

- стиль;
- профиль;
- агрессию;
- motion intent;
- preferred orifice;
- soft/hard behavior;
- target amplitude/speed/force preferences.

Paudi не должна напрямую ломать низкоуровневую геометрию:

- не выбирать shaftAxis вместо Geometry Layer;
- не подменять targetEntry вне Planner;
- не перехватывать outside capture прямым offset-ом, если активна новая система.

Текущие Paudi-файлы:

- `FuckingReach.PaudiUI.cs`;
- `FuckingReach.PaudiRuntimeAndLearning.cs`;
- `FuckingReach.PaudiAutopilotAndUtils.cs`;
- `FuckingReach.PaudiProfilesAndProps.cs`.


4. Новая математика
-------------------

4.1. Главная координата - параметр `s`

На shaft вводится параметр:

- `s = 0`: начало shaft / точка надевания;
- `s > 0`: глубина вдоль shaft;
- `s = shaftLength`: конец shaft.

Фазы используют `s` так:

- `Rendezvous`: target не на оси, а в свободной точке рядом с `s ~= 0`.
- `TipCapture`: targetEntry выходит на `s = 0`.
- `AxisMount`: targetEntry движется от `s = 0` к holdDepth.
- `InsideFollow`: targetEntry удерживается около holdDepth.
- `Thrust`: `s` колеблется вокруг holdDepth с amplitude/speed.


4.2. Rendezvous target

Rendezvous - это отдельная точка подвода. Ее нельзя путать с targetEntry на
оси shaft.

Она строится из:

- shaftStart;
- shaft frame;
- clearanceUp;
- clearanceRadial;
- текущей стороны подхода;
- мягкого уменьшения clearance при сближении.

Главная цель Rendezvous:

    Не тянуть бедра вниз/вперед в стержень, а сначала вывести entry в свободную
    точку, из которой возможна нормальная посадка.


4.3. TargetEntry

После Rendezvous targetEntry должен лечь на shaft axis.

Это жесткий target solver-а, а не примерная точка для hip.


4.4. Channel direction

Не надо насильно делать:

    channelAxis == shaftAxis

Нужно:

- задать preferred direction;
- ограничить угол comfort cone;
- дать слайдерам pitch/yaw/roll bias;
- резать bias, если он уводит entry center с оси shaft.


5. Что переписывать в текущих файлах
-----------------------------------

5.1. `FuckingReach.SmartGuardsAndShaft.cs`

Перевести shaft truth на synthetic shaft.

Кандидаты на переработку:

- `GetStablePenisDirection` - сделано, удален из активного кода;
- `TryGetCurrentShaftMotionTruth` - частично сделано, оставлен только как
  compatibility wrapper поверх `ShaftTruth`;
- outside/inside shaft helpers;
- directed entry helpers;
- старые sign reference helpers.


5.2. `FuckingReach.HipApproach.cs`

Разобрать `SmartDriveHipControlDirect` на этапы:

- collect truth;
- update phase;
- build target;
- solve pose;
- apply emergency guards;
- apply result.

Этот файл сейчас главный узел подвода, отвода/withdraw, reinsert, outside aim,
inside aim и axis-mount. Его нельзя бесконечно лечить новыми offset-ами.


5.3. `FuckingReach.SmartCore.cs`

Выделить:

- phase state;
- inside stable;
- axis guard;
- smart secondary rig;
- smart profile/body wave.

Все, что относится к planner/solver, постепенно выносить в новые файлы.


5.4. `FuckingReach.Geometry.PenisColliders.cs`

Оставить старые penis collider helpers как fallback/debug.

Новая geometry truth должна жить отдельно, чтобы старые collider эвристики не
перетягивали решение.


5.5. `FuckingReach.ThrustAndArousal.cs`

Перевести thrust на depth по shaft `s`.

Траст не должен сам выбирать outside aim. Его вход:

- current mounted state;
- holdDepth;
- amplitude;
- speed/frequency;
- force scale;
- guard limits.


5.6. Paudi-файлы

Paudi оставить как layer намерений:

- style/profile;
- target force/frequency/amplitude;
- body language;
- soft intent.

Paudi не должна напрямую исправлять ошибки capture своей отдельной геометрией.


6. Порядок работ
----------------

Этап 0. Базовая безопасность

- Не менять сразу поведение и архитектуру одним коммитом/проходом.
- После каждого этапа проверять загрузку `FuckingReach.cslist` в VaM.
- Не трогать старый одиночный файл без отдельной причины.
- Любой новый runtime `.cs` добавлять в `FuckingReach.cslist`.
- Черновые `.cs` можно держать вне `FuckingReach.cslist`, но активные файлы не
  должны ссылаться на них до отдельной проверки загрузки в VaM.
- Писать код под VaM-совместимый C# не старше C# 6.
- Не использовать новые конструкции языка, которые могут быть несовместимы с
  VaM/Unity Mono: pattern matching, `out var`, tuples, local functions,
  expression-bodied members, modern collection syntax.
- Не использовать `System.Reflection` и reflection-style API:
  `BindingFlags`, `GetField`, `GetProperty`, `InvokeMember`, `MethodInfo`,
  `FieldInfo` и похожие обходные механизмы.
- Когда новый rod-centric/synthetic участок берет поведение на себя, старый
  управляющий путь в этом же месте нужно удалять или отключать. Нельзя
  оставлять старый aim/route/solver как запасной маршрут, потому что тогда тест
  не показывает, работает новая система или ее незаметно спасает legacy-код.
- Разрешены только safety fallback-и от краша и физического взрыва: null/finite
  checks, anti-teleport, anti-explosion, явный "ничего не делать в этот кадр".
  Они не должны выбирать маршрут и не должны строить старую цель.
- Если в новой фазе нет валидного `ShaftTruth` / `OrificeTruth`, фаза должна
  явно остановиться или показать состояние вроде `NoOutsideTruth`, а не
  незаметно переходить на base/mid/tip, maleHip.forward или corridor-эвристику.
- После добавления новой функции нужно проверить соседний старый код и удалить
  мусор: неиспользуемые helper-ы, fallback-точки, старые clamp-и в роли руля,
  дублирующие вычисления target/axis/depth.
- Если игра вылетает без сообщения об ошибке, не делать автоматический полный
  откат. Сначала изолировать последний маленький шаг, сделать его пассивным или
  безопасным, проверить компиляцию и только потом продолжать.


Этап 1. Инвентаризация конфликтов

Составить карту текущего управления:

- кто сейчас считает aim;
- кто двигает hip target;
- кто крутит hip/pelvis;
- какие clamps могут давить вниз;
- какие Paudi offsets вмешиваются;
- какие старые reinsert/inside helpers включаются во время outside approach.

Результат этапа:

- комментарии/таблица в debug или отдельном документе;
- список методов, которые надо отключать по фазам.


Этап 2. Debug metrics

Добавить видимые и логируемые метрики:

- current phase;
- shaftStart/shaftEnd/shaftAxis;
- entryPointWorld;
- channelAxisWorld;
- rendezvousTarget;
- targetEntryWorld;
- desiredChannelWorld;
- entry lateral error;
- entry depth `s`;
- channel angle error;
- twist error;
- active legacy guards;
- current movement owner.

Без этого дальнейшие правки будут слепыми.


Этап 3. Geometry truth

Сделать новый источник truth:

- `ShaftTruth`;
- `OrificeTruth`;
- projection по `s`;
- stable entry/channel в local space.

На этом этапе еще не надо полностью менять движение. Сначала надо доказать, что
truth стабилен и debug показывает правильные точки.


Этап 4. Planner state machine

Добавить phase state:

- `AcquireTarget`;
- `Rendezvous`;
- `TipCapture`;
- `AxisMount`;
- `InsideFollow`;
- `Thrust`;
- `Recover`.

Planner должен строить targets, но не двигать контроллеры.


Этап 5. Pose solver

Сделать solver, который принимает:

- targetEntry;
- desired channel/allowed cone;
- current hip/pelvis;
- phase weights.

И возвращает:

- target position;
- target rotation;
- error metrics;
- safety flags.

Первый solver может быть простым, но его API должен быть правильным.


Этап 6. Врезать solver в Smart

`SmartDriveHipControlDirect` перевести на pipeline:

    truth -> planner -> solver -> emergency guards -> apply

Старые outside clamps на этом этапе не удалять, но перевести в gated/emergency
режим.


Этап 7. Mount -> InsideFollow -> Thrust

После стабильного outside capture:

- AxisMount двигает entry по `s` к holdDepth;
- InsideFollow держит entry на оси shaft;
- Thrust колеблет `s`;
- guards не перехватывают главный маршрут.


Этап 8. Paudi integration

Paudi подключается как intent layer:

- force/frequency/amplitude preferences;
- motion style;
- body language;
- aggression/softness;
- orifice preference.

Paudi не должна напрямую строить competing outside capture target.


Этап 9. Regression tests

Проверять минимум:

- стержень спереди снизу;
- стержень спереди сверху;
- стержень сбоку;
- стержень сзади;
- стержень далеко вне оси;
- shaft смотрит вверх;
- shaft смотрит вниз;
- разные отверстия;
- разные углы channelAxis;
- разные slider biases;
- Paudi off/on;
- thrust off/on;
- смена отверстия во время outside;
- потеря capture и recover.


7. Текущий статус выполнения
----------------------------

Уже сделано:

- создана многофайловая структура в папке `FuckingReach`;
- создан и используется список загрузки `FuckingReach.cslist`;
- исходный монолит разнесен на набор `.cs` файлов через `partial class
  FuckingReach`;
- добавлен отдельный partial-модуль `FuckingReach.HipApproach.cs`;
- в `FuckingReach.HipApproach.cs` структурно вынесены текущие методы подвода,
  отвода/withdraw, reinsert, outside/inside aim, rendezvous, axis-mount и
  entry-centered hip target;
- `SmartDriveHipControlDirect` теперь находится в `FuckingReach.HipApproach.cs`;
- `FuckingReach.cslist` обновлен и включает `FuckingReach.HipApproach.cs`;
- добавлен `FuckingReach.HipApproachDebug.cs`;
- включен первый диагностический snapshot для HipApproach:
  phase, owner, flags, aim/reference/final target, lateral/axis/depth errors,
  movement step;
- HipApproach debug выводится через существующий `Show rod-centric smart debug`;
- добавлен `FuckingReach.GeometryTruth.cs`;
- введены первые структуры `ShaftTruth` и `OrificeTruth`;
- GeometryTruth считает shaft base/tip/axis/length/radius, projection `s`,
  depth from tip, lateral error, tip distance и directed/undirected axis angle;
- GeometryTruth подключен к debug-выводу и первым маленьким runtime-куском:
  outside rod aim берет `shaft.Tip/Axis/Length` и
  `orifice.EntryWorld/EntryRadius` через `ShaftTruth`/`OrificeTruth`;
- `ShaftTruth` больше не вызывает collider radius estimation на каждом чтении:
  радиус берется из уже рассчитанной synthetic curve radii, с fallback;
- outside-подвод больше не строит основную цель через старое
  `hip.control.position + aimDelta`: при `outsideRodGuide` цель бедер сразу
  считается через entry-centered solve `entry -> aimPoint`;
- в `GetSmartOutsideEntryCenteredHipTarget` убрано мягкое подмешивание
  результата к старой fallback-цели; метод возвращает решенную hip target
  напрямую, а ограничение скорости остается на общем apply-слое;
- старое `hip + aimDelta` больше даже не вычисляется как базовая цель для
  `outsideRodGuide`; оно остается только для не-outside/legacy/inside участков;
- добавлен outside truth gate: `outsideRodGuide` не продолжает работу без
  валидных `ShaftTruth` и `OrificeTruth`;
- удален старый `GetSmartOutsideReferencePoint` fallback: outside reference
  берется прямо из `OrificeTruth.EntryWorld`;
- `TryGetSmartOutsideRodAim` больше не собирает цель через fallback
  `TryGetCurrentShaftMotionTruth` / `TryGetStableSyntheticOrificeTruth`;
  для outside rod aim нужны обе truth-модели;
- `GetSmartOutsideDesiredAxis` переведен на `ShaftTruth` / `OrificeTruth` и
  больше не пересобирает outside axis через старый motion-truth/orifice helper;
- в outside direction blend заменен `Vector3.Slerp` на более простой
  `Vector3.Lerp` + normalize, чтобы уменьшить риск нестабильных направлений;
- `GetSmartAimPoint` больше не возвращает старую segment-tip цель `segB`, если
  outside rod aim не смог построиться; вместо этого цель остается на текущем
  входе отверстия, чтобы отсутствие truth было видно сразу;
- `GetSmartAimPoint` больше не строит старый `base -> tip` segment перед
  outside aim; outside сразу идет через `TryGetSmartOutsideRodAim`;
- legacy aim prediction отключен для `outsideRodGuide`, чтобы rod-centric
  rendezvous/entry target не уезжал от synthetic truth из-за предыдущего кадра;
- `TryGetCurrentShaftTruth` теперь читает активную synthetic shaft centerline
  напрямую из `syntheticPenisCurvePoints[0..last]` и не строит runtime truth через
  `TryGetCurrentShaftMotionTruth`;
- `SmartDriveHipControlDirect` получает основной `stableDir`, `shaftBasePos`,
  `shaftTipPos` и `penisLen` из `ShaftTruth`, а не через старую ось
  `GetStablePenisDirection` / `TryGetCurrentShaftMotionTruth`;
- проверки reinsert/contact в HipApproach (`IsSmartSelectedOrificeContactWellAligned`,
  `ShouldSuppressSmartPoseReinsertForRodGuide`) теперь используют
  `ShaftTruth` / `OrificeTruth`, а не старую ось по penis controls;
- inside fallback в `GetSmartAimPoint` теперь проецирует цель на
  `ShaftTruth.Base -> ShaftTruth.Tip`, а не на segment из старого motion-truth;
- `TryGetSmartInsideAimPair` больше не строит inside segment от
  `smoothedPenisBasePosition`; он берет `Base/Tip/Axis/Length` из `ShaftTruth`;
- inside axial RB/controller sync и safety clamp вход в HipApproach теперь
  используют `shaftBasePos` из `ShaftTruth`, а не `smoothedPenisBasePosition`;
- `TryGetPenetrationMetrics` и `TryGetShaftDepthFraction` переведены на
  `ShaftTruth` + `OrificeTruth`: глубина и lateral error считаются от центра
  synthetic shaft, а не от surface/envelope стержня;
- основные thrust/inside-follow метрики в `FuckingReach.ThrustAndArousal.cs`
  теперь берут `shaft.Base/Axis/Length` из `ShaftTruth`, без fallback на старую
  `TryGetCurrentShaftMotionTruth` в этих функциях;
- inside target на shaft теперь строится как точка на centerline по глубине
  `Simple hold depth from tip`, без подмешивания радиуса отверстия и без
  удержания случайно достигнутой более глубокой позиции;
- outside `AxisMount` теперь тоже использует полную глубину
  `Simple hold depth from tip`, а не урезанные 20-30% и не radius-bias;
- outside mount transition теперь считается не только от точного попадания в
  tip/centerline, но и от входа entry в цилиндр/канал synthetic shaft;
- когда outside capture уже близок к mount, движение разделяется по оси shaft,
  чтобы цель уходила в глубину, а не продолжала диагонально гоняться за tip;
- основной thrust получил hard-gate `IsSmartRodThrustMounted`: non-prop thrust
  не запускается, пока entry выбранного synthetic отверстия не находится внутри
  shaft channel/cylinder и не достигло требуемой глубины от tip;
- depth tolerance hard-gate оставлен строгим, а lateral tolerance теперь
  считается от shaft radius + entry radius tolerance, чтобы разрешить траст при
  entry внутри канала стержня, а не только на идеальной centerline;
- к lateral tolerance thrust permission добавлен внешний допуск 3 см диаметра
  (+1.5 см радиуса). Сам synthetic shaft/channel radius не меняется;
- этот hard-gate теперь также запрещает non-prop thrust, если нет валидного
  active synthetic orifice / `OrificeTruth`;
- во время inside/thrust старый full `ClampHipToMaleAnchor` больше не должен
  ограничивать бедра по продольной оси тела мужчины; вместо него добавлен
  side-only male-center bias: центр берется из позиции `penisBaseControl`, а
  left/right направление берется из костей/rigidbody мужских бедер, не из
  shaft direction и не из направления контроллеров, с 2.5 см свободной зоной
  влево и 2.5 см вправо (5 см суммарно);
- для Rigidbody thrust добавлен мягкий side-only assist, который демпфирует
  левый/правый срыв бедер без запрета движения к ногам/голове;
- для mounted thrust добавлен soft hip positional anchor с 2.5 см free radius
  (5 см суммарной боковой дорожки);
  он держит бедра около позиции начала траста, но мягко следует за боковым
  смещением базы synthetic shaft;
- anchor теперь не переустанавливает позицию по таймеру во время валидного
  траста, а HipApproach при активном anchor перестает привязывать axial target к
  текущему drift Rigidbody;
- `IsSmartRodThrustMounted` получил разделение start/continue: старт thrust
  остается строгим по hold depth, а продолжение при активном thrust-anchor
  держится, пока entry/channel еще реально на shaft, чтобы один плохой кадр или
  просадка depth не запускали reinsert/retreat;
- HipApproach теперь подавляет smart reinsert, пока активен mounted thrust anchor,
  чтобы система не снимала отверстие со стержня после нескольких толчков;
- `SimpleForce` direction / reverse direction / distance-to-tip теперь читают
  `ShaftTruth`, если он валиден, и не строят трастовую цель по старому
  base/mid/tip направлению;
- runtime hip-force update и Smart pitch snap переведены на `ShaftTruth`;
- cached `currentPenisDirection` после построения synthetic shaft теперь равен
  centerline axis от base к tip, а не tangent последнего сегмента у tip;
- старый `GetStablePenisDirection` удален из активного кода: вызовов больше нет;
- `TryGetCurrentShaftMotionTruth` оставлен только как compatibility wrapper для
  старых UI/status участков и теперь сначала делегирует в `TryGetCurrentShaftTruth`;
- добавлен `FuckingReach.HipApproachRotationLock.cs`;
- на outside/mount фазах HipApproach включает Y/Z-lock для hip/бедренного рига;
- при активном Y/Z-lock body-wave больше не добавляет roll/Z в linked rig;
- в `FuckingReach.HipApproach.cs` стабилизирован outside rendezvous normal:
  free rendezvous target больше не должен строиться радиальным вектором вниз
  против reference-up, что уменьшает старое поведение "бедра давят вниз";
- в outside rendezvous normal убран рискованный `Vector3.Slerp` на
  противоположных направлениях; используется C# 6 / Unity-safe `Vector3.Lerp`
  с проверкой finite;
- добавлен `FuckingReach.SmartPlanner.cs`;
- введены первые формальные фазы Smart planner-а:
  `AcquireTarget`, `Rendezvous`, `TipCapture`, `AxisMount`, `InsideFollow`,
  `Thrust`, `Recover`, `LegacyOutside`;
- `FuckingReach.SmartPlanner.cs` оставлен на диске как черновик, но временно
  исключен из `FuckingReach.cslist`, чтобы проверить, связан ли hard crash VaM с
  самим подключением нового файла;
- исходный одиночный `FuckingReach_V5_rigibody.cs` не изменялся в ходе
  разнесения;
- создан `README.md` с описанием назначения каждого файла;
- файл `Схема - план действий.txt` очищен от сырого чата и превращен в рабочую
  дорожную карту;
- проверены ссылки в `FuckingReach.cslist`;
- проверен баланс скобок во всех `.cs` файлах;
- проверено, что количество найденных методов в разнесенной версии совпадает с
  исходником;
- зафиксировано правило: на фазах подвода, позиционирования и одевания запрещать
  управляющее Y/Z вращение hip и бедренного рига;
- зафиксировано и реализовано правило side-only центрирования:
  корректировать только левый/правый срыв относительно позиции `penisBaseControl`
  и left/right оси от костей/rigidbody мужских бедер, не зажимая движение к
  ногам или голове;
- зафиксировано и реализовано правило mounted thrust hip anchor:
  positional-only, 2.5 см free radius, capture once at thrust start, no timed
  recapture, radial correction is projected off shaft axis so it does not block
  axial thrust, HipApproach axial target respects anchor, follows shaft-base
  lateral movement, uses short mount hysteresis, no torque;
- hip sliders (`Hip tilt`, `Hip yaw`, `Hip roll`) снова являются видимым
  источником поворота hip: Smart rotation lock сохраняет slider yaw/roll, а
  ручной slider-demand получает минимальную скорость поворота даже при слабом
  Smart rotation strength;
- mounted thrust теперь не должен прерываться reinsert/switch-флагами, если
  synthetic truth показывает, что entry/channel все еще на shaft; в этой же
  фазе HipApproach пропускает legacy safety corridors, чтобы они не душили
  валидный траст;
- `Linked rig speed multiplier` теперь влияет не только на secondary rig, но и
  на скорость/step основного HipApproach move; `Aiming strength (position)`
  использует весь диапазон 0..3 и при 0 реально гасит позиционное наведение;
- в debug overlay для synthetic vagina/anus добавлены отдельные cyan
  `EntryRing`-кольца ровно на `entryPos`, чтобы было видно реальное начало
  отверстия и канала, отдельно от линии канала и колец capsule collider;
- `TryGetSmartInsideAimPair` при включенном `Simple hip hold` теперь строит
  inside target как `shaft.PointFromTipDepth(Simple hold depth from tip)`, а
  reference берет от фактического synthetic entry center. Слайдер глубины стал
  реальной целью entry на centerline, а не слабой подсказкой после ray/segment
  closest-point;
- inside axial follow больше не урезает axial correction, когда selected entry
  уже хорошо сидит на shaft и активен `Simple hip hold`; в этом случае hold
  depth напрямую владеет осевой поправкой, а HipApproach не подменяет эту осевую
  цель синхронизацией с текущим drift Rigidbody;
- `ApplySmartRodHoldDepthAssist` теперь удерживает точную глубину от tip с малой
  deadzone, без прежнего soft-exit люфта в несколько сантиметров, и получил
  более сильную пружину/демпфер против сползания entry к base;
- hip tilt/yaw/roll sliders снова работают как простой slider bias без
  predictive/rebound автоматики. Во время подвода, отвода, reinsert и switch
  Smart-gate по-прежнему не дает им скручивать hip; при mounted thrust и в
  обычном ручном режиме они применяются напрямую;
- над hip sliders добавлен общий выключатель `Hip sliders rotate hips`
  (default ON). Если выключить, `Hip tilt`/`Hip yaw`/`Hip roll` остаются
  видимыми значениями, но больше не вращают hip и не пишутся Paudi/preset-ами;
- для hip sliders добавлены пользовательские пределы: `Предел Hip tilt (°)`
  0..40, `Предел Hip yaw (°)` 0..40 и `Предел Hip roll (°)` 0..20. Presets и
  Paudi масштабируют свои старые цели пропорционально этим пределам: например
  предел 15 означает движение только в диапазоне -15..+15;
- запись hip sliders сглажена сильнее: цели фильтруются медленнее, скорость
  SmoothDamp масштабируется от текущего пользовательского предела, чтобы малые
  пределы не давали резкого дергания значений;
- старый hip zero-lock отключен: Smart settle/pose cooldown больше не
  обнуляет видимые `Hip tilt`/`Hip yaw`/`Hip roll`, а только синхронизирует
  внутреннее сглаживание с текущими значениями в рамках заданных пределов;
- side-only male-center leash переписан как ограничитель по костям/rigidbody
  бедер мужского/target Person: центр берется от `penisBaseControl`, направление
  left/right берется из `lThigh/rThigh` bones, а не из penis/controller forward;
- боковой leash теперь мерит selected synthetic entry, если он валиден, и только
  fallback-ом сам hip target. Внутри ±2.5 см от центра он ничего не делает
  (суммарная дорожка 5 см), за пределом корректирует только left/right
  компоненту, повторно применяется после Paudi offsets и дополнительно дает
  Rigidbody-assist в SmartApproach, а не только во время thrust;
- outside/withdraw/reinsert alignment больше не берет боковой вектор подвода как
  desired channel axis: при подводе/отводе канал целится в shaft/penis axis, а
  Smart применяет pitch-only X alignment для hip и связанного рига.
- добавлен mounted hip-slider recovery: если во время траста lateral/axis метрики
  selected synthetic entry уходят в опасный перекос, система не сбрасывает
  видимые hip sliders, а временно уменьшает их вклад в rotation/offset и дает
  Smart rotation больше веса, чтобы вернуть канал к shaft axis и продолжить
  thrust без reinsert-паузы;
- `IsSmartRodThrustMounted` получил recoverable-режим для активного anchor:
  краткий сильный перекос до допустимого предела больше не выключает thrust, а
  запускает recovery, если depth/lateral еще показывают, что entry на shaft;
- `Simple hold depth from tip` теперь при фактическом контакте/inside/mounted
  не догоняет цель медленной пружиной: axial offset выставляется сразу, inside
  axial follow отдается hold depth, а `ApplySmartRodHoldDepthAssist` усилен и
  работает с меньшей deadzone против сползания entry к base;
- ноль hip sliders теперь привязан к baseline текущей загруженной позы:
  возврат sliders около 0 и mounted-перекос больше не перезаписывают
  `CaptureInitialHipBaseline`; сильный engaged-поворот запускает recovery, а не
  становится новой точкой отсчета.

Финальный проход по этому плану:

- активный `FuckingReach.SmartPlanner.cs` подключен в `.cslist` без nested
  enum/struct и ведет phase/owner плюс Y/Z lock для approach/mount;
- активный `FuckingReach.HipUniversalSolver.cs` подключен как entry-centered
  solver: он строит target entry/depth/axis от `ShaftTruth` + `OrificeTruth`,
  решает hip target через локальный offset entry относительно hip, а в
  Rendezvous/TipCapture/AxisMount/Recover теперь напрямую владеет outside target,
  чтобы legacy aim не мог увести бедра от выбранного отверстия;
- добавлен entry-progress guard: slider, male-center bias, thrust anchor,
  outside body clamp, MoveTowards и final step откатываются, если их новая
  цель уводит selected entry дальше от universal solver target;
- guard получил axis-setup исключение только для `MoveTowards` и `FinalStep`:
  если шаг идет ближе к solver hip target при плохой оси, ему разрешено
  временно чуть ухудшить текущую entry-distance, чтобы бедра/риг могли
  докрутиться и найти solvable pose;
- solver preview приведен к реальному ограничению rotation: только X/pitch,
  без yaw/roll. Если yaw/roll нужен стилем, это остается за hip sliders/Paudi
  style layer, а низкоуровневый solver добирает положение движением бедер;
- для Rendezvous/TipCapture при плохой axis добавлен minimum axis-speed, чтобы
  бедра могли уйти вперед/назад вдоль shaft/body еще до AxisMount;
- добавлена axis feasibility логика: если канал/shaft axis слишком далеко от
  допустимого cone для AxisMount, planner откатывает фазу в TipCapture и держит
  entry у pre-entry/tip вместо попытки насадить при невозможной оси;
- runtime yaw/roll recovery остается выключенным; debug `Pipeline` показывает
  `yawRoll` и `yzLock`, чтобы убедиться, что yaw/roll не включились случайно;
- male-center Rigidbody assist больше не применяется, пока universal solver
  владеет outside/recover target;
- активный `FuckingReach.DepthServo.cs` стал общим depth-corridor helper:
  HipApproach, mounted stroke servo, thrust axis anchor и rod hold depth assist
  теперь читают один evaluated corridor state вместо разрозненного min/max/edge
  пересчета;
- Paudi low-level hip converge больше не владеет shaft/orifice navigation, когда
  planner/solver/depth активны; Paudi остается слоем ритма, rocking, tilt/roll,
  comfort и body expression;
- debug теперь показывает `Pipeline`, `Planner`, `UniversalSolver`,
  `DepthServo`, `PaudiGuard` и `OwnerHistory`, чтобы было видно, кто реально
  управляет движением;
- старые опасные `.disabled/.backup` черновики с nested types вынесены из
  VaM-папки в архив workspace.

Единственное, что нельзя закрыть статическим редактированием кода: реальные
regression tests в VaM по front/back/side/top/bottom, разным отверстиям и
hard/soft режимам. Кодовая часть pipeline на этот момент собрана.


8. Критерии готовности
----------------------

Система считается собранной, когда:

- из любой точки route сначала идет в свободную Rendezvous-точку;
- front approach не давит бедра вниз и вперед;
- во время подвода/позиционирования/mount нет управляющего Y/Z вращения hip и
  бедренного рига;
- entry center выходит к shaftStart/pre-entry, а не ниже shaft;
- при mount entry center садится на shaft axis;
- channelAxis не флипается;
- одна и та же математика работает для front/back/side/top/bottom;
- thrust работает как движение по shaft depth `s`;
- старые clamps не диктуют route;
- debug показывает, кто управляет движением и какие guards активны;
- Paudi влияет на стиль и намерение, но не ломает geometry truth.


9. Главный принцип
------------------

Не лечить каждый проблемный ракурс отдельным offset-ом.

Правильная цель:

    shaft truth + stable orifice truth + phase planner + entry-centered solver.

Если новая правка добавляет отдельный костыль для front/back/side вместо общей
геометрии, значит она почти наверняка ведет систему обратно к старому хаосу.


10. Последняя правка: эмоции/дыхание возбуждения
------------------------------------------------

- исправлена логика выбора режима эмоций: runtime теперь понимает английские
  значения UI `Auto`, `Natural`, `Ahegao`, `Ahegao climax`, `Off`, а также старые
  русские варианты, поэтому выбор `Ahegao` больше не должен проваливаться в
  дефолтный/авто-режим;
- явный режим `Ahegao` теперь сразу дает полный входной drive, который затем
  масштабируется слайдерами силы, а `Ahegao climax` включается только во время
  стадий кончания;
- поиск морфов расширен: кроме `morphsControlUI` проверяются `morphBank1/2/3`,
  добавлены имена HK/BodyLanguage для рта, глаз, языка и дыхания;
- ахегао-глаза теперь временно отключают не только `lookAt.on`, но и
  `lookAt.enabled`, чтобы штатный VaM gaze не перетягивал глаза обратно;
- в UI эмоций и дыхания добавлены статусные строки с текущим drive и счетчиком
  найденных морфов. Если `morphs 0`, значит логика включилась, но на модели не
  найден нужный morph/display name.
- следующая правка по результату теста: эмоции и дыхание теперь по умолчанию
  включены; явный режим `Ahegao` больше не зависит от master-переключателя
  `Enable arousal system`, чтобы выбор был виден прямо в меню;
- перед первым запуском эмоций и при смене режима выполняется сброс лицевых и
  языковых морфов, которыми управляет плагин, к default value; это не должно
  брать текущую мимику сцены как baseline;
- в меню `Эмоции` добавлена кнопка `Reset emotions`, которая вручную сбрасывает
  управляемые лицевые/языковые морфы и перезапускает чистую базу;
- tongue для ахегао разделен на отдельные morph targets: `Tongue In-Out`,
  `Tongue Raise-Lower`, `Tongue Up-Down`, чтобы не применять неправильный знак
  к `Raise-Lower`;
- для явного `Ahegao` eye-drive дополнительно поднимается минимум до 0.92, чтобы
  выбранный режим был визуально заметен даже при умеренных strength sliders.


11. Правка HK natural / BL breathing
------------------------------------

- натуральный режим эмоций приведен ближе к оригинальному HK: добавлен
  недостающий слой Joy (`AAmouth_smile1/2/3/4/6` и
  `AA_smilecheeks1/2/3`), группы выбирают один активный morph на 3-15 секунд,
  а значение считается как в HK через `Lerp(0.10, max, intensity)`;
- добавлен UI-слайдер `HK joy strength`, который управляет HK-улыбкой/щеками
  от текущего `Arousal level`; pain-слой в бесплатном HK не имеет дефолтных
  expression groups, поэтому копировать там нечего;
- natural/HK режим не забирает управление глазами через кости и `EyesControl`:
  bone/LookAt override остается только у `Ahegao`, а при выходе из него
  `lookAt` восстанавливается сразу, чтобы Glance мог снова вести взгляд;
- исправлен конфликт дублей морфов: reset-слоты больше не должны перетирать
  активный natural/ahegao target того же DAZMorph, а неактивные слоты с нулевым
  current не пишут default value каждый кадр;
- дыхание переведено ближе к BodyLanguage: period считается как
  `2.5 * (1 - intensity)^2 + 0.75`, соотношение вдох/выдох меняется от
  стимуляции, а `BL_Breathing_Chest`, `BL_RibCageDefine` и
  `BL_Breathing_Stomach` получают двусторонний вдох/выдох от шкалы возбуждения,
  скорости траста и climax boost.
- hotfix после теста: для явного режима `Natural` добавлен видимый минимум
  natural-drive `0.35` при включенном `Enable arousal system`, чтобы HK-морфы
  не оставались на почти незаметном уровне `0.04` до набора шкалы возбуждения.
- если в явном `Natural` не найден ни один HK-морф (`morphs 0`), включается
  fallback на базовые morph names (`Mouth Open`, `Eyes Wide`, `Brows Arch`,
  `Eyes Squint`), чтобы режим не выглядел полностью выключенным на модели без
  нужного HK morph pack.


12. Hotfix: полный сброс эмоций и глаз
--------------------------------------

- кнопка `Reset emotions` теперь делает жесткий сброс: заново находит все
  лицевые/языковые morph targets, которыми пользуется система эмоций, сразу
  записывает им default value и обнуляет runtime targets/velocity;
- при выключении `Arousal emotions enabled` выполняется такой же жесткий сброс,
  а не плавное затухание, чтобы ахегао не оставляло глаза/язык/рот в сцене;
- при `OnDisable` и `OnDestroy` плагина вызывается общий reset presentation,
  поэтому при выключении или удалении плагина эмоции, дыхательные morph slots,
  VAMMoan state и bone-override глаз должны освобождаться сразу;
- ахегао-глаза теперь сбрасываются отдельным hard path: eye blend/target/velocity
  обнуляются, `lEye/rEye` возвращаются к сохраненной базе, а если базы нет
  после перезагрузки - к `Quaternion.identity`; затем сразу восстанавливается
  штатный `EyesControl/LookAt`.


13. Hotfix: Natural/HK expression regression
--------------------------------------------

- режим `Natural` больше не должен забирать глазные яблоки у Glance: при входе
  в Natural/Off или при нулевом ahegao-drive выполняется release только
  ahegao eye override, а сами HK natural expressions работают только через
  morph groups лица/век/рта;
- HK natural expression groups теперь ближе к оригиналу: activation thresholds
  считаются по сырому `Arousal level`, а слайдеры `Emotion overall strength`,
  `Natural emotion strength` и `HK joy strength` масштабируют только силу
  morph value, чтобы low/mid/high mouth groups не сдвигались вниз из-за
  strength sliders;
- для рта добавлен небольшой `natural_voice_mouth_open`, который открывает
  `Mouth Open` во время активных VAMMoan states (`Breathing Mouth`, `Moaning`,
  `Orgasm`), чтобы natural-мимика не выглядела закрытой во время звука;
- управление VAMMoan2 приведено ближе к HK: вместо простого
  `Disabled/Moaning/Orgasm` теперь отправляются состояния `Breathing Idle`,
  `Breathing Nose`, `Breathing Mouth`, `Moaning`, `Orgasm`.


14. Hotfix: Glance release + anti-drift бедер
---------------------------------------------

- при выходе из `Ahegao` в `Natural/Off` release больше не пишет вращения
  `lEye/rEye`; он только обнуляет ahegao eye runtime и сразу возвращает
  `EyesControl/LookAt`, чтобы Glance снова мог управлять глазными яблоками;
- hard reset глаз оставлен для `Reset emotions`, выключения и удаления плагина,
  поэтому ручной/финальный сброс по-прежнему очищает зависшие ahegao-глаза;
- в не-жестком режиме удержания после стабильного траста добавлен мягкий
  anti-drift: hipControl продолжает следить за текущим synthetic orifice и
  подтягивает его центр к оси стержня без движения вдоль стержня;
- дополнительно добавлен roll anti-drift: крен бедер корректируется вокруг
  текущей оси стержня относительно позы, которая была зафиксирована в момент
  парковки вторичного рига;
- коррекция ограничена маленькими шагами и дополняется слабым Rigidbody assist,
  чтобы не превращать режим обратно в жесткий риг и не ломать текущий Natural.


15. Paudi Mind: главный слой поведения
--------------------------------------

- добавляется отдельный верхний слой `Paudi Mind`, который должен быть главным
  источником намерения для систем движения; профили и пресеты Paudi считаются
  только слабыми подсказками старого UI и не должны владеть финальным поведением;
- для живой сцены действует жесткое правило: не кэшировать кости, контроллеры,
  позиции, вращения и вычисленную геометрию; все такие данные читать свежими в
  момент расчета. Разрешено хранить только внутреннее состояние Paudi Mind
  (желание, нежность, страсть, текущая фраза движения), потому что это не кэш
  сцены;
- первый этап подключает Paudi Mind к `Hip Wiggle`: вместо узких диапазонов от
  profile/preset финальные цели радиуса, скорости, фазы, разгона, торможения и
  эллипса берутся из Mind-фраз (`Hold`, `Build`, `Wide Slow`, `Ride`, `Tease`,
  `Explore`, `Recover`, `Impulsive`);
- на медленном трасте Paudi Mind может поднимать радиус Wiggle к крупным
  значениям 28-40 см, не зажимаясь около 20-22; на быстром трасте сохраняется
  более компактное поведение;
- фаза Hip Wiggle в Mind предпочитает противофазу, обычно 120-180 градусов,
  и не должна проваливаться в маленькие значения;
- скорость Wiggle держится близко к живой частоте траста, но не прибивается
  математически один-в-один: допускается небольшой дрейф, чтобы движение не
  выглядело роботизированным;
- второй этап подключает этот же слой как финальное намерение для траста,
  тела, дыхания и эмоций: старые профили/пресеты сначала могут дать базовый
  расчет, но перед применением целей Paudi Mind переписывает/смешивает
  частоту, силу, амплитуду, грудь, колени, дыхание и expression-drive;
- для траста Mind выдает собственную живую цель частоты/силы/амплитуды:
  медленные фразы могут быть широкими и тягучими, быстрые остаются компактнее,
  а плохой угол/боковое смещение снижает силу и глубину;
- для тела Mind финально управляет hip tilt/yaw/roll, chest, knee spread и
  knee height перед записью в слайдеры, поэтому колени/грудь больше не должны
  оставаться только под старым profile/preset слоем;
- для дыхания Mind меняет глубину и частоту поверх текущего breathing system,
  но при активном трасте держит темп близко к live thrust frequency;
- для эмоций Mind влияет на Natural/Joy/Ahegao targets: Natural остается
  живым до climax, climax может усилить Ahegao, а явный Off остается
  выключающим режимом.
